package vip.liux.front.infrastructure.jpa.coupon;

import jakarta.persistence.criteria.Predicate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import vip.liux.contracts.models.coupon.Coupon;
import vip.liux.contracts.repositories.coupon.CouponRepository;
import vip.liux.contracts.shared.enums.Status;
import vip.liux.contracts.shared.enums.coupon.CouponType;

import java.time.LocalDateTime;
import java.util.List;

public interface CouponJpaRepository extends JpaRepository<Coupon, Long>, CouponRepository, JpaSpecificationExecutor<Coupon> {

    @Override
    @Query("select c from Coupon c where c.status = vip.liux.contracts.shared.enums.Status.ENABLED" +
            " and c.receiveStart <= current_timestamp and c.receiveEnd >= current_timestamp order by c.creationTime desc")
    List<Coupon> findQueryAvailableCoupons();

    @Override
    default Page<Coupon> findByPage(String couponName, CouponType couponType, Status status, LocalDateTime receiveStart, LocalDateTime receiveEnd, Pageable pageable) {
        return findAll((root, q, cb) -> {
            List<Predicate> predicates = new java.util.ArrayList<>();
            if (couponName != null && !couponName.isEmpty()) {
                predicates.add(cb.like(root.get("couponName"), "%" + couponName + "%"));
            }
            if (couponType != null) {
                predicates.add(cb.equal(root.get("couponType"), couponType));
            }
            if (status != null) {
                predicates.add(cb.equal(root.get("status"), status));
            }
            if (receiveStart != null) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("receiveStart"), receiveStart));
            }
            if (receiveEnd != null) {
                predicates.add(cb.lessThanOrEqualTo(root.get("receiveEnd"), receiveEnd));
            }
            return cb.and(predicates.toArray(new Predicate[0]));
        }, pageable);
    }
}